/**
 * 
 */
package com.service.api.adcenter;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javax.xml.rpc.ServiceException;

import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.AdPosition;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.Currency;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.EstimatedBidAndTraffic;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.KeywordAndConfidence;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.KeywordEstimatedBid;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.KeywordHistoricalPerformance;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.KeywordKPI;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.KeywordSuggestion;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.MatchType;
import org.datacontract.schemas._2004._07.Microsoft_AdCenter_Advertiser_CampaignManagement_Api_DataContracts.TimeInterval;

import com.microsoft.adapi.AdApiFaultDetail;
import com.microsoft.adcenter.v8.AdIntelligenceServiceLocator;
import com.microsoft.adcenter.v8.ApiFaultDetail;
import com.microsoft.adcenter.v8.BasicHttpBinding_IAdIntelligenceServiceStub;
import com.microsoft.adcenter.v8.GetEstimatedBidByKeywordsRequest;
import com.microsoft.adcenter.v8.GetEstimatedBidByKeywordsResponse;
import com.microsoft.adcenter.v8.GetHistoricalKeywordPerformanceRequest;
import com.microsoft.adcenter.v8.GetHistoricalKeywordPerformanceResponse;
import com.microsoft.adcenter.v8.IAdIntelligenceService;
import com.microsoft.adcenter.v8.SuggestKeywordsFromExistingKeywordsRequest;
import com.microsoft.adcenter.v8.SuggestKeywordsFromExistingKeywordsResponse;
import com.pub.i.AttributesI;
import com.pub.util.MathUtil;
import com.service.vo.KeywordVo;

/**
 * @author iling
 *
 */
public class AdIntelligenceService implements AttributesI
{
	private static long accountId = 256490;
	
	private static String userName;
	private static String password;
	private static String applicationToken;
	private static String developerToken;	

	private static String namespace ;
	private static String url;

	private static MatchType[] matchType = { MatchType.Phrase };
	
	private static AdIntelligenceServiceLocator adServiceLocator;
	private static IAdIntelligenceService service;
	
	private int limit;
	
	public AdIntelligenceService(ResourceBundle rb)
	{
		if(service == null) 
			init(rb);
	}
	
	public void setLimit(int limit)
	{
		this.limit = limit;
	}
	
	public boolean init(ResourceBundle rb)
	{
		boolean isReturn = true;
		
		userName 		= rb.getString("msdn.api.user.name");
		password 		= rb.getString("msdn.api.user.passwd");
		applicationToken= rb.getString("msdn.api.applicationToken");
		developerToken 	= rb.getString("msdn.api.developerToken");

		namespace 		= rb.getString("msdn.api.namespace");
		url 			= rb.getString("msdn.api.url");
		
		String accountIdStr = rb.getString("msdn.api.accountId");
		if(accountIdStr.matches("[\\d]+"))
			accountId = Long.parseLong(accountIdStr);
		else
			System.err.println("MSDN account id format error.");

		adServiceLocator = new AdIntelligenceServiceLocator();
		
		try {
			adServiceLocator.setBasicHttpBinding_IAdIntelligenceServiceEndpointAddress(url);
			
			service = adServiceLocator.getBasicHttpBinding_IAdIntelligenceService();
			
			BasicHttpBinding_IAdIntelligenceServiceStub stub = (BasicHttpBinding_IAdIntelligenceServiceStub)service;
			
			stub.setHeader(namespace, "ApplicationToken", applicationToken);
			stub.setHeader(namespace, "DeveloperToken", developerToken);
			stub.setHeader(namespace, "UserName", userName);
			stub.setHeader(namespace, "Password", password);
			stub.setHeader(namespace, "CustomerAccountId", accountId);
			
		} catch (ServiceException e) {
			isReturn = false;
			
			e.printStackTrace();
		}
		
		return isReturn;
	}
	
	public List<KeywordVo> getEstimatedBid(List<KeywordVo> keywordList) throws AdApiFaultDetail, ApiFaultDetail, RemoteException
	{
		int dataSize = keywordList.size();
		
		if(keywordList == null || dataSize == 0)
			return new ArrayList<KeywordVo>();

		String[] keywords = new String[dataSize];
		
		for(int i = 0; i <  dataSize ; i++){
			keywords[i] = keywordList.get(i).getKeyword();
	    }

		GetEstimatedBidByKeywordsRequest req = new GetEstimatedBidByKeywordsRequest();
		req.setKeywords(keywords);
		req.setMatchTypes(matchType);
		req.setCurrency(Currency.USDollar);
		
		GetEstimatedBidByKeywordsResponse res = service.getEstimatedBidByKeywords(req);
		
		KeywordEstimatedBid[] keb = res.getKeywordEstimatedBids();
		
		if(keb != null){
			Double averageCpc;
			Double averageImpression;
			Double averageClicks;
			Double averageTotalCost;

			for(int i = 0; i < keb.length; i++){
				for(KeywordVo keywordVO : keywordList){
	        		if(keywordVO.getKeyword().equals(keb[i].getKeyword())){
	        			EstimatedBidAndTraffic[] ebt = keb[i].getEstimatedBids();
	    				
	    				for(int j = 0; j < ebt.length; j++){
	    					averageCpc 			= MathUtil.round(ebt[j].getAverageCPC(), 4);
	    					averageClicks 		= MathUtil.round((ebt[j].getMinClicksPerWeek() + ebt[j].getMaxClicksPerWeek()) / 2.0, 4);
	    					averageImpression	= MathUtil.round((ebt[j].getMinImpressionsPerWeek() + ebt[j].getMaxImpressionsPerWeek()) / 2.0, 4);
	    					averageTotalCost	= MathUtil.round((ebt[j].getMinTotalCostPerWeek() + ebt[j].getMaxTotalCostPerWeek()) / 2.0, 4);
	    					
		        			keywordVO.put(AttributesI.ESTIMATES_AVERAGE_CPC, averageCpc.toString());
		        			keywordVO.put(AttributesI.ESTIMATES_AVERAGE_IMPRESSION, averageImpression.toString()); 	// average impression per week
		        			keywordVO.put(AttributesI.ESTIMATES_CLICKS, averageClicks.toString());					// average clicks per week
		        			keywordVO.put(AttributesI.ESTIMATES_TOTAL_COST, averageTotalCost.toString());				// average total cost per week
	    				}
	        		}
	        	}
				
			}
		}else{
			System.out.println("KeywordEstimatedBid is null ");
		}
		
		return keywordList;
	}
	
	public List<KeywordVo> getHistoricalKeywordStats(List<KeywordVo> keywordList, MatchType matchType, AdPosition adPostion, TimeInterval timeInterval) throws AdApiFaultDetail, ApiFaultDetail, RemoteException
	{
		int dataSize = keywordList.size();
		
		if(keywordList == null || dataSize == 0)
			return new ArrayList<KeywordVo>();

		String[] keywords = new String[dataSize];
		
		for(int i = 0; i <  dataSize ; i++){
			keywords[i] = keywordList.get(i).getKeyword();
	    }

		GetHistoricalKeywordPerformanceRequest req = new GetHistoricalKeywordPerformanceRequest();
		req.setKeywords(keywords);
		req.setMatchType(matchType);
		req.setTargetAdPosition(adPostion);
		req.setTimeInterval(timeInterval);
		
		GetHistoricalKeywordPerformanceResponse res = service.getHistoricalKeywordPerformance(req);
		
		KeywordHistoricalPerformance[] khp = res.getKeywordHistoricalPerformances();
		
		if(khp != null){
			Integer impressions;
			Integer	clicks;
			
			Double 	totalCost;
			Double 	averageCpc;
			Double 	CTR;

			for(int i = 0; i < khp.length; i++){
				if(khp[i] == null)
					continue;
				
				for(KeywordVo keywordVO : keywordList){
	        		if(keywordVO.getKeyword().equals(khp[i].getKeyword())){
	        			
	        			KeywordKPI[] kkpi = khp[i].getKeywordKPIs();
	        			
	    				for(int j = 0; j < kkpi.length; j++){
	    					averageCpc 	= MathUtil.round(kkpi[j].getAverageCPC(), 4);
	    					clicks 		= kkpi[j].getClicks();
	    					impressions	= kkpi[j].getImpressions();
	    					totalCost	= kkpi[j].getTotalCost();
	    					CTR			= kkpi[j].getCTR();
	    					
	    					keywordVO.put(AttributesI.HISTORICAL_AVERAGE_CPC, String.format("%.4f", averageCpc));
	    					keywordVO.put(AttributesI.HISTORICAL_IMPRESSIONS, impressions.toString());
	    					keywordVO.put(AttributesI.HISTORICAL_CLICKS, clicks.toString());
	    					keywordVO.put(AttributesI.HISTORICAL_TOTAL_COST, String.format("%.4f", totalCost));
	    					keywordVO.put(AttributesI.HISTORICAL_CTR, String.format("%.4f", CTR));
	    				}
	        		}
	        	}
				
			}
		}else{
			System.out.println("KeywordHistoricalPerformance is null ");
		}
		
		return keywordList;
	}
	
	public KeywordVo getHistoricalKeywordStats(String keyword, MatchType matchType, AdPosition adPostion, TimeInterval timeInterval) throws AdApiFaultDetail, ApiFaultDetail, RemoteException
	{
		if(keyword == null)
			return null;
		
		String[] keywords = new String[]{keyword};
		
		GetHistoricalKeywordPerformanceRequest req = new GetHistoricalKeywordPerformanceRequest();
		req.setKeywords(keywords);
		req.setMatchType(matchType);
		req.setTargetAdPosition(adPostion);
		req.setTimeInterval(timeInterval);

		GetHistoricalKeywordPerformanceResponse res = service.getHistoricalKeywordPerformance(req);
		
		KeywordHistoricalPerformance[] khp = res.getKeywordHistoricalPerformances();
		
		KeywordVo keywordVO = null;
		
		if(khp != null){
			Integer impressions;
			Integer	clicks;
			
			Double 	totalCost;
			Double 	averageCpc;
			Double 	CTR;

			for(int i = 0; i < khp.length; i++){
				if(khp[i] == null)
					continue;
				
        		if(keyword.equalsIgnoreCase(khp[i].getKeyword())){
        			keywordVO = new KeywordVo();
        			KeywordKPI[] kkpi = khp[i].getKeywordKPIs();
        			
    				for(int j = 0; j < kkpi.length; j++){
    					averageCpc 	= MathUtil.round(kkpi[j].getAverageCPC(), 4);
    					clicks 		= kkpi[j].getClicks();
    					impressions	= kkpi[j].getImpressions();
    					totalCost	= kkpi[j].getTotalCost();
    					CTR			= kkpi[j].getCTR();
    					
	        			keywordVO.put(AttributesI.HISTORICAL_AVERAGE_CPC, String.format("%.4f", averageCpc));
	        			keywordVO.put(AttributesI.HISTORICAL_IMPRESSIONS, impressions.toString());
	        			keywordVO.put(AttributesI.HISTORICAL_CLICKS, clicks.toString());
	        			keywordVO.put(AttributesI.HISTORICAL_TOTAL_COST, String.format("%.4f", totalCost));
	        			keywordVO.put(AttributesI.HISTORICAL_CTR, String.format("%.4f", CTR));
    				}
    				
    				break;
        		}
			}
		}else{
//			System.out.println("getHistoricalKeywordStats is null ");
		}
		
		return keywordVO;
	}
	
	public KeywordVo getHistoricalKeywordStats(KeywordVo keyword, MatchType matchType, AdPosition adPostion, TimeInterval timeInterval) throws AdApiFaultDetail, ApiFaultDetail, RemoteException
	{
		if(keyword == null)
			return null;
		
		String[] keywords = new String[]{keyword.getKeyword()};
		
		GetHistoricalKeywordPerformanceRequest req = new GetHistoricalKeywordPerformanceRequest();
		req.setKeywords(keywords);
		req.setMatchType(matchType);
		req.setTargetAdPosition(adPostion);
		req.setTimeInterval(timeInterval);

		GetHistoricalKeywordPerformanceResponse res = service.getHistoricalKeywordPerformance(req);
		
		KeywordHistoricalPerformance[] khp = res.getKeywordHistoricalPerformances();
		
		if(khp != null){
			Integer impressions;
			Integer	clicks;
			
			Double 	totalCost;
			Double 	averageCpc;
			Double 	CTR;

			for(int i = 0; i < khp.length; i++){
				if(khp[i] == null)
					continue;
				
        		if(keyword.getKeyword().equalsIgnoreCase(khp[i].getKeyword())){
        			KeywordKPI[] kkpi = khp[i].getKeywordKPIs();
        			
    				for(int j = 0; j < kkpi.length; j++){
    					averageCpc 	= MathUtil.round(kkpi[j].getAverageCPC(), 4);
    					clicks 		= kkpi[j].getClicks();
    					impressions	= kkpi[j].getImpressions();
    					totalCost	= kkpi[j].getTotalCost();
    					CTR			= kkpi[j].getCTR();
    					
    					keyword.put(AttributesI.HISTORICAL_AVERAGE_CPC, String.format("%.4f", averageCpc));
    					keyword.put(AttributesI.HISTORICAL_IMPRESSIONS, impressions.toString());
    					keyword.put(AttributesI.HISTORICAL_CLICKS, clicks.toString());
    					keyword.put(AttributesI.HISTORICAL_TOTAL_COST, String.format("%.4f", totalCost));
    					keyword.put(AttributesI.HISTORICAL_CTR, String.format("%.4f", CTR));
    				}
    				
    				break;
        		}
			}
		}else{
//			System.out.println("getHistoricalKeywordStats is null ");
		}
		
		return keyword;
	}
	
	public List<KeywordVo> getSuggestKeywords(String keywords) throws AdApiFaultDetail, ApiFaultDetail, RemoteException
	{
		List<KeywordVo> keywordList = new ArrayList<KeywordVo>();
		
		SuggestKeywordsFromExistingKeywordsRequest request = new SuggestKeywordsFromExistingKeywordsRequest();
		request.setKeywords(new String[] { keywords });
		
		request.setMaxSuggestionsPerKeyword(limit);
		
		SuggestKeywordsFromExistingKeywordsResponse response = service.suggestKeywordsFromExistingKeywords(request);
		
		KeywordSuggestion[] keb = response.getKeywordSuggestions();
		
		if(keb != null){
			for(int i = 0; i < keb.length; i++){
				if(keb[i] == null)
					continue;
				
				KeywordAndConfidence[] ebt = keb[i].getSuggestionsAndConfidence();
				
				for(int j = 0; j < ebt.length; j++){
					KeywordVo vo = new KeywordVo();
		    		
					vo.setKeyword(ebt[j].getSuggestedKeyword());
					
					keywordList.add(vo);
				}
			}
		}
		
		return keywordList;
	}
}
